package edu.ntnu.superrss.models;

import com.sun.syndication.feed.impl.CopyFromHelper;
import com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.module.DCModule;
import com.sun.syndication.feed.module.DCModuleImpl;
import com.sun.syndication.feed.module.Module;
import com.sun.syndication.feed.module.SyModule;
import com.sun.syndication.feed.module.SyModuleImpl;
import com.sun.syndication.feed.synd.SyndContent;
import com.sun.syndication.feed.synd.SyndEnclosure;
import com.sun.syndication.feed.synd.SyndEnclosureImpl;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.*;

/**
 *
 * @author Sigurd Fosseng <sigurd at fosseng.net>
 */
@Entity
@Table(name="SYND_ENTRY")
public class SyndEntryImpl implements Serializable, SyndEntry, Comparable{
	private ObjectBean objBean;
	private Long entryID;
	private String uri;
	private String title;
	private String link;
	private Date publishedDate;
	private String author;
	private List links;
	private SyndContent description;
	private SyndFeed source;
	private Date updatedDate;
	private List<SyndContent> contents;
	private List foreginMarkup;
        private List<Comment> comments = new ArrayList<Comment>();
        private Long thumbsUp = 0L;

	@Id
	@GeneratedValue
	@Column(name="ENTRY_ID")
	public Long getEntryID() {
		return entryID;
	}

	public void setEntryID(Long id) {
		this.entryID = id;
	}



	public String getUri() {
		return uri;
	}

	public void setUri(String uri) {
		this.uri = uri;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

        public Long getThumbsUp() {
            return thumbsUp;
        }

        public void setThumbsUp(Long thumbsUp) {
            this.thumbsUp = thumbsUp;
        }

        public void incrementThumbsUp() {
            this.thumbsUp++;
        }

        public void decrementThumbsUp() {
            this.thumbsUp--;
        }
        
	@Transient
	public SyndContent getTitleEx() {
		SyndContent s = new SyndContentImpl();
		s.setValue(title);
		return s;
	}

	public void setTitleEx(SyndContent title) {
		this.title = title.getValue();
	}

	public String getLink() {
		return link;
	}

	public void setLink(String link) {
		this.link = link;
	}
	@Transient
	public List getLinks() {
		return links;
	}

        @Override
        public boolean equals(Object entry) {
            return this.getEntryID().equals(((SyndEntryImpl) entry).getEntryID());
        }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 29 * hash + (this.entryID != null ? this.entryID.hashCode() : 0);
        hash = 29 * hash + (this.uri != null ? this.uri.hashCode() : 0);
        return hash;
    }

	public void setLinks(List links) {
		this.links = links;
	}
	@OneToOne(targetEntity=SyndContentImpl.class, cascade=CascadeType.ALL)
	public SyndContent getDescription() {
		return description;
	}

	public void setDescription(SyndContent description) {
		this.description = description;
	}

        @JoinTable(name="ELEMENT_CONTENT")
	@OneToMany(targetEntity=SyndContentImpl.class, cascade=CascadeType.ALL)
	public List getContents() {
		return (contents==null) ?(contents=new ArrayList()):contents;
	}

	public void setContents(List contents) {
		this.contents = contents;
	}
	@Transient
	public List getEnclosures() {
		return new ArrayList<String>();
	}

	public void setEnclosures(List enclosures) {
		
	}

	@Temporal(javax.persistence.TemporalType.TIMESTAMP)
	public Date getPublishedDate() {
		return publishedDate;
	}

	public void setPublishedDate(Date publishedDate) {
            if(publishedDate == null){
                publishedDate = new Date();
            }
		this.publishedDate = publishedDate;
	}

	@Temporal(javax.persistence.TemporalType.TIMESTAMP)
	public Date getUpdatedDate() {
		return updatedDate;
	}

	public void setUpdatedDate(Date updatedDate) {
		this.updatedDate = updatedDate;
	}
	@Transient
	public List getAuthors() {
		return new ArrayList();
	}

	public void setAuthors(List authors) {
		
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}
	@Transient
	public List getContributors() {
		return new ArrayList();
	}

	public void setContributors(List contributors) {
		
	}
	@Transient
	public List getCategories() {
		return new ArrayList();
	}

	public void setCategories(List categories) {
		
	}
	@ManyToOne(targetEntity=SyndFeedImpl.class,cascade=CascadeType.ALL)
	public SyndFeed getSource() {
		return source;
	}
	public void setSource(SyndFeed source) {
		this.source = source;
	}
	@Transient
	public Object getWireEntry() {
		return new Object();
	}
	public Module getModule(String uri) {
		throw new UnsupportedOperationException("Not supported yet.");
	}
	@Transient
	public List getModules() {
		return new ArrayList();
	}

	public void setModules(List modules) {
		
	}
	@Transient
	public Object getForeignMarkup() {
		return(foreginMarkup == null)?(foreginMarkup=new ArrayList()):foreginMarkup;
	}

	public void setForeignMarkup(Object foreignMarkup) {
		this.foreginMarkup = (List)foreginMarkup;
	}
	@Transient
	public Class getInterface() {
		return SyndEntry.class;
	}
    	@Override
	public Object clone() throws CloneNotSupportedException {
		return objBean.clone();
	}



    @OneToMany(fetch=FetchType.EAGER, targetEntity= Comment.class, cascade = CascadeType.ALL)
    public List getComments() {
        return this.comments;
    }

    public void setComments(List comments) {
        this.comments = comments;
    }

    public void addComment(Comment comment) {
        comment.setPublishedDate(new Date());
        this.comments.add(comment);
    }

    public int compareTo(Object o) {
       return this.getPublishedDate().compareTo(((SyndEntryImpl) o).getPublishedDate());
    }

          //Utilizes CopyFromHelper from the ROME API
      private static final CopyFromHelper COPY_FROM_HELPER;
      static {
            Map basePropInterfaceMap = new HashMap();
            basePropInterfaceMap.put("uri",String.class);
            basePropInterfaceMap.put("title",String.class);
            basePropInterfaceMap.put("link",String.class);
            basePropInterfaceMap.put("uri",String.class);
            basePropInterfaceMap.put("description",SyndContent.class);
            basePropInterfaceMap.put("contents",SyndContent.class);
            basePropInterfaceMap.put("enclosures",SyndEnclosure.class);
            basePropInterfaceMap.put("modules",Module.class);
            basePropInterfaceMap.put("publishedDate", Date.class);

            Map basePropClassImplMap = new HashMap();
            basePropClassImplMap.put(SyndContent.class,SyndContentImpl.class);
            basePropClassImplMap.put(SyndEnclosure.class,SyndEnclosureImpl.class);
            basePropClassImplMap.put(DCModule.class,DCModuleImpl.class);
            basePropClassImplMap.put(SyModule.class,SyModuleImpl.class);

            COPY_FROM_HELPER = new CopyFromHelper(SyndEntry.class,basePropInterfaceMap,basePropClassImplMap);
      }

      public void copyFrom(Object obj) {
            COPY_FROM_HELPER.copy(this, obj);
      }
}
